package com.ruoyi.task.service.impl;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.hutool.core.util.IdUtil;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.category.domain.SysBackpack;
import com.ruoyi.category.service.ISysBackpackService;
import com.ruoyi.category.service.ISysSubjectService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.RedisConstants;
import com.ruoyi.common.constant.SysConstants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.TaskStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.http.HttpUtilDo;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.system.service.ISysDictTypeService;
import com.ruoyi.task.domain.SysFault;
import com.ruoyi.task.domain.SysTask;
import com.ruoyi.task.domain.SysTaskStep;
import com.ruoyi.task.mapper.SysTaskMapper;
import com.ruoyi.task.service.ISysFaultService;
import com.ruoyi.task.service.ISysTaskStepService;
import org.apache.http.HttpResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.task.mapper.SysUserTaskMapper;
import com.ruoyi.task.domain.SysUserTask;
import com.ruoyi.task.service.ISysUserTaskService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 用户任务Service业务层处理
 * 
 * @author ruoyi
 * @date 2022-06-23
 */
@Service
public class SysUserTaskServiceImpl implements ISysUserTaskService 
{
    @Autowired
    private SysUserTaskMapper sysUserTaskMapper;

    @Autowired
    private SysTaskMapper sysTaskMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ISysSubjectService subjectService;

    @Autowired
    private ISysDictTypeService dictTypeService;

    @Autowired
    private ISysBackpackService sysBackpackService;

    @Autowired
    private ISysFaultService sysFaultService;

    @Autowired
    private ISysTaskStepService sysTaskStepService;


    /**
     * 查询用户任务
     * 
     * @param id 用户任务主键
     * @return 用户任务
     */
    @Override
    public SysUserTask selectSysUserTaskById(Long id)
    {
        return sysUserTaskMapper.selectSysUserTaskById(id);
    }

    /**
     * 查询用户任务列表
     * 
     * @param sysUserTask 用户任务
     * @return 用户任务
     */
    @Override
    public List<SysUserTask> selectSysUserTaskList(SysUserTask sysUserTask) {
        List<SysUserTask> userTaskList = sysUserTaskMapper.selectSysUserTaskList(sysUserTask);

        for (SysUserTask list : userTaskList) {
            if (list.getStartTime() != null && list.getSubmitTime() != null) {
                String diffTime = DateUtils.getTaskDatePoor(list.getSubmitTime(), list.getStartTime());
                list.setDurationTime(diffTime);
            }
            list.setUrl(Constants.HOST_IP+list.getUrl());
        }
        return userTaskList;
    }

    /**
     * api查询用户任务列表
     *
     * @param sysUserTask 用户任务
     * @return 用户任务
     */
    @Override
    public List<SysUserTask> selectApiUserTaskList(SysUserTask sysUserTask) {
        Long userId = SecurityUtils.getUserId();
        sysUserTask.setUserId(userId);
        //获取模式
       if(StringUtils.isNull(sysUserTask.getPattern())){
           if (StringUtils.isNotNull(redisCache.getCacheMapValue(RedisConstants.WORK_PATTERN, userId.toString()))) {
               sysUserTask.setPattern(redisCache.getCacheMapValue(RedisConstants.WORK_PATTERN, userId.toString()));
           } else {
               throw new ServiceException("工作模式错误");
           }
       }
        List<SysUserTask> userTaskList = sysUserTaskMapper.selectApiUserTaskList(sysUserTask);
        //任务编号集合
        List<Long> taskNoList = userTaskList.stream().map(u -> u.getTaskNo()).collect(Collectors.toList());
        Long[] taskNos = taskNoList.toArray(new Long[taskNoList.size()]);
        List<SysFault> faultList = new ArrayList<>();
        List<SysTaskStep> taskStepList = new ArrayList<>();
        if(taskNos.length > 0){
            //故障现象
            SysFault sysFault = new SysFault();
            sysFault.setArrayTaskNo(taskNos);
            faultList = sysFaultService.selectSysFaultList(sysFault);
            //任务步骤
            SysTaskStep stepParam = new SysTaskStep();
            stepParam.setTaskNos(taskNos);
            taskStepList = sysTaskStepService.selectSysTaskStepList(stepParam);
        }
        for (SysUserTask list : userTaskList) {
            //故障现象
            List<SysFault> faList = new ArrayList<>();
            for (SysFault fault : faultList) {
                if (Objects.equals(list.getTaskNo(),fault.getTaskNo())) {
                    SysFault addFault = new SysFault();
                    addFault.setChildName(fault.getChildName());
                    addFault.setWeight(fault.getWeight());
                    faList.add(addFault);
                }
            }
            //任务步骤
            List<SysTaskStep> stepList = new ArrayList<>();
            for (SysTaskStep taskStep : taskStepList) {
                if (Objects.equals(list.getTaskNo(),taskStep.getTaskNo())) {
                    SysTaskStep step = new SysTaskStep();
                    BeanUtils.copyProperties(taskStep, step);
                    stepList.add(step);
                }
            }
            list.setFaultList(faList);
            list.setStepList(stepList);
            //时长
            if (list.getStartTime() != null && list.getSubmitTime() != null) {
                String diffTime = DateUtils.getTaskDatePoor(list.getSubmitTime(), list.getStartTime());
                list.setDurationTime(diffTime);
            }
        }
        return userTaskList;
    }

    /**
     * 新增用户任务
     * 
     * @param sysUserTask 用户任务
     * @return 结果
     */
    @Override
    public int insertSysUserTask(SysUserTask sysUserTask)
    {
        sysUserTask.setCreateTime(DateUtils.getNowDate());
        return sysUserTaskMapper.insertSysUserTask(sysUserTask);
    }

    /**
     * 批量新增用户任务
     *
     * @param userTaskList 用户任务List
     * @return 结果
     */
    @Override
    public int insertSysUserTaskAll(List<SysUserTask> userTaskList)
    {

        return sysUserTaskMapper.insertSysUserTaskAll(userTaskList);
    }

    /**
     * 修改用户任务
     * 
     * @param sysUserTask 用户任务
     * @return 结果
     */
    @Override
    public int updateSysUserTask(SysUserTask sysUserTask)
    {
        sysUserTask.setUpdateTime(DateUtils.getNowDate());
        return sysUserTaskMapper.updateSysUserTask(sysUserTask);
    }

    /**
     * 前端-修改用户任务
     *
     * @param sysUserTask 用户任务
     * @return 结果
     */
    @Override
    public int updateUserTask(SysUserTask sysUserTask)
    {
        if (StringUtils.isNull(sysUserTask.getUserId()) || sysUserTask.getUserId() == 0) {
            throw new ServiceException("用户ID不能为空");
        }
        sysUserTask.setUpdateTime(DateUtils.getNowDate());
        return sysUserTaskMapper.updateSysUserTask(sysUserTask);
    }

    /**
     * 批量删除用户任务
     * 
     * @param ids 需要删除的用户任务主键
     * @return 结果
     */
    @Override
    public int deleteSysUserTaskByIds(Long[] ids)
    {
        return sysUserTaskMapper.deleteSysUserTaskByIds(ids);
    }

    /**
     * 删除用户任务信息
     * 
     * @param id 用户任务主键
     * @return 结果
     */
    @Override
    public int deleteSysUserTaskById(Long id)
    {
        return sysUserTaskMapper.deleteSysUserTaskById(id);
    }

    /**
     * 更新个人任务状态
     * @param sysUserTask
     * @return
     */
    @Override
    public int updateUserTaskStatus(SysUserTask sysUserTask) {
        //查询任务参与人数
        SysTask sysTask = new SysTask();
        sysTask.setTaskNo(sysUserTask.getTaskNo());
        List<SysTask> taskList = sysTaskMapper.selectSysTaskList(sysTask);
        if (StringUtils.isEmpty(taskList)) {
            throw new ServiceException("任务数据有误,请查看是否存在有任务编号为:" + sysUserTask.getTaskNo() + "的任务");
        }

        int headcount = taskList.get(0).getHeadcount();
        if (sysUserTask.getStatus() == SysConstants.CONSTANT_INT0) {
            headcount += 1;
        } else {
            headcount = headcount > 0 ? headcount - 1 : 0;
        }
        //更新任务参与人数
        sysTask.setTaskId(taskList.get(0).getTaskId());
        sysTask.setHeadcount(headcount);
        sysTask.setUpdateTime(DateUtils.getNowDate());
        sysTask.setTaskNo(null);
        sysTaskMapper.updateSysTask(sysTask);
        //更新个人任务启用状态
        sysUserTask.setUpdateTime(DateUtils.getNowDate());
        return sysUserTaskMapper.updateSysUserTask(sysUserTask);
    }

    /**
     * 根据任务编号修改用户任务信息
     * @param sysUserTask
     * @return
     */
    @Override
    public int updateUserTaskByTaskNo(SysUserTask sysUserTask) {
        sysUserTask.setUpdateTime(DateUtils.getNowDate());
        return sysUserTaskMapper.updateUserTaskByTaskNo(sysUserTask);
    }

    /**
     * 删除用户任务
     * @param userTask
     * @return
     */
    @Override
    public int deleteUserTask(SysUserTask userTask)
    {
        return sysUserTaskMapper.deleteUserTask(userTask);
    }


    /**
     * 前端-获取用户已创建任务列表
     *
     * @param sysUserTask 用户任务
     * @return 用户任务
     */
    @Override
    public List<SysUserTask> taskCreateList(SysUserTask sysUserTask) {
        Long userId = SecurityUtils.getUserId();
        sysUserTask.setUserId(userId);
        //获取模式,如果前端不传模式值，则直接获取登录时选择的模式
       if(StringUtils.isNull(sysUserTask.getPattern())){
           if (StringUtils.isNotNull(redisCache.getCacheMapValue(RedisConstants.WORK_PATTERN, userId.toString()))) {
               sysUserTask.setPattern(redisCache.getCacheMapValue(RedisConstants.WORK_PATTERN, userId.toString()));
           } else {
               throw new ServiceException("工作模式错误");
           }
       }
        List<SysUserTask> userTaskList = sysUserTaskMapper.taskCreateList(sysUserTask);
        //任务科目(故障类型)
        SysDept sysSubject = new SysDept();
        sysSubject.setType(SysConstants.CONSTANT_STR5);
        List<SysDept> subject = subjectService.selectSubjectList(sysSubject);
        //任务模式
        String taskTypeName = Constants.SYS_TASK_MODEL;
        List<SysDictData> taskTypeList = dictTypeService.selectDictDataByType(taskTypeName);
        //所选背包
        List<SysBackpack> backpackList = sysBackpackService.selectSysBackpackList(null);
        //终端类型
        String terminalType = Constants.SYS_TERMINAL_TYPE;
        List<SysDictData> terminalList = dictTypeService.selectDictDataByType(terminalType);

        //任务编号集合
        List<Long> taskNoList = userTaskList.stream().map(u -> u.getTaskNo()).collect(Collectors.toList());
        Long[] taskNos = taskNoList.toArray(new Long[taskNoList.size()]);
        List<SysFault> faultList = new ArrayList<>();
        List<SysTaskStep> taskStepList = new ArrayList<>();
        if(taskNos.length > 0) {
            SysFault sysFault = new SysFault();
            sysFault.setArrayTaskNo(taskNos);
            //故障现象集合
            faultList = sysFaultService.selectSysFaultList(sysFault);
            //任务步骤
            SysTaskStep stepParam = new SysTaskStep();
            stepParam.setTaskNos(taskNos);
            taskStepList = sysTaskStepService.selectSysTaskStepList(stepParam);
        }
        //组装数据
        for(SysUserTask userTask : userTaskList){
            //故障现象
            List<SysFault> faList = new ArrayList<>();
            for (SysFault fault : faultList) {
                if (userTask.getTaskNo().equals(fault.getTaskNo())) {
                    SysFault addFault = new SysFault();
                    addFault.setChildName(fault.getChildName());
                    addFault.setWeight(fault.getWeight());
                    faList.add(addFault);
                }
            }
            userTask.setFaultList(faList);

            //任务步骤
            List<SysTaskStep> stepList = new ArrayList<>();
            for (SysTaskStep taskStep : taskStepList) {
                if (userTask.getTaskNo().equals(taskStep.getTaskNo())) {
                    SysTaskStep step = new SysTaskStep();
                    BeanUtils.copyProperties(taskStep, step);
                    stepList.add(step);
                }
            }
            userTask.setStepList(stepList);
            //设置科目名称
            for (SysDept su : subject) {
                if (Objects.equals(userTask.getFaultSubjectId(), su.getDeptId().intValue())) {
                    userTask.setDeptName(su.getDeptName());
                }
            }
            //设置任务模式名称
            for (SysDictData taskType : taskTypeList) {
                if (Objects.equals(userTask.getTaskType(), Integer.parseInt(taskType.getDictValue()))) {
                    userTask.setTaskTypeName(taskType.getDictLabel());
                }
            }

            //设置背包
            for (SysBackpack backpack : backpackList) {
                if (Objects.equals(userTask.getBackpack(), backpack.getBackpackId().intValue())) {
                    userTask.setSysBackpack(backpack);
                }
            }

            //设置终端名称
            for (SysDictData terminal : terminalList) {
                if (Objects.equals(userTask.getTaskType(), Integer.valueOf(terminal.getDictValue()))) {
                    userTask.setTerminalName(terminal.getDictLabel());
                }
            }
        }
        return userTaskList;
    }


    /**
     * 获取视频流
     *
     * @param taskId 用户任务ID
     * @return 视频流信息
     */
     @Override
     public Map<String, String> getRtsp(String taskId) throws Exception {
         //检查redis缓存是否存在，redis缓存不存在查询所有信息，写入缓存
         String hKey = SysConstants.RTSP_URL + taskId ;
         if(StringUtils.isNull(redisCache.getCacheMapValue(RedisConstants.RTSP_VIDEO,hKey))){
             //组装header参数
             Map<String, String> headers = new HashMap<>();
             headers.put("token", SysConstants.RTSP_TOKEN);
             Map<String, String> query = new HashMap<>();
             //执行get请求
             HttpResponse httpResponse =  HttpUtilDo.doGet(SysConstants.RTSP_HOST, SysConstants.RTSP_PATH, headers, query);
             String result = HttpUtilDo.getHttpEntityContent(httpResponse);
             if(StringUtils.isNotBlank(result)){
                 JSONObject jsonObject = JSON.parseObject(result);
                 if(StringUtils.isNotNull(jsonObject)){
                     JSONObject payloads = jsonObject.getJSONObject("payload");
                     for (Map.Entry<String, Object> entry : payloads.entrySet()) {
                         String url = new JSONObject((Map) entry.getValue()).getJSONObject("channels").getJSONObject("0").get("url").toString();
                         //缓存到redis
                         redisCache.setCacheMapValue(RedisConstants.RTSP_VIDEO,url,entry.getKey());
                         //更新过期时间
                         redisCache.expire(RedisConstants.RTSP_VIDEO,RedisConstants.EXPIRE_TIME_120, TimeUnit.MINUTES);
                     }
                 }
             }
         }

         //更新缓存后如果还是不存在，则执行新增操作
         if(StringUtils.isNull(redisCache.getCacheMapValue(RedisConstants.RTSP_VIDEO,hKey))){
             //组装链接
             String uuid = IdUtil.randomUUID();
             String path = "/stream/" + uuid + "/add";

             //组装提交数据结构
             Map<String,Object> param = new HashMap<>();
             Map<String,Object> channel = new HashMap<>();
             Map<String,Object> demand = new HashMap<>();
             demand.put("url", hKey);
             demand.put("on_demand", true);
             demand.put("on_demand", false);
             channel.put("0", demand);
             param.put("name", taskId );
             param.put("channels", channel);

             //执行POST请求
             String url = SysConstants.RTSP_HOST+path;
             String value = JSON.toJSONString(param);
             String response = HttpUtils.sendPostRaw(url, value);
             if (StringUtils.isNotBlank(response)) {
                 //新增成功则写入缓存
                 if (1 == (int) JSON.parseObject(response).get("status")) {
                     // 缓存到redis
                     redisCache.setCacheMapValue(RedisConstants.RTSP_VIDEO, hKey, uuid);
                     //更新过期时间
                     redisCache.expire(RedisConstants.RTSP_VIDEO,RedisConstants.EXPIRE_TIME_120, TimeUnit.MINUTES);
                 }
             }
         }

         //获取uuid
         String uid = "";
         if (StringUtils.isNotNull(redisCache.getCacheMapValue(RedisConstants.RTSP_VIDEO, hKey))) {
             uid = redisCache.getCacheMapValue(RedisConstants.RTSP_VIDEO, hKey).toString();
         }
         //组装返回信息
         Map<String, String> data = new HashMap<>();
         data.put("ip",SysConstants.RTSP_IP);
         data.put("uuid",uid);
         return data;
     }

    /**
     * 前端-通过任务编号获取用户已创建任务列表
     *
     * @param sysUserTask 用户任务
     * @return 用户任务
     */
    @Override
    public List<SysUserTask> personList(SysUserTask sysUserTask) {
        if (StringUtils.isNull(sysUserTask.getTaskNo())) {
            throw new ServiceException("任务编号不能为空！");
        }
        String taskPerson = RedisConstants.TASK_PERSON + sysUserTask.getTaskNo();
        List<SysUserTask> personList = sysUserTaskMapper.taskCreateList(sysUserTask);

        //将人员信息、准备状态写到redis
        for (SysUserTask person : personList) {
            if(StringUtils.isNull(redisCache.getCacheMapValue(taskPerson,person.getUserId().toString()))){
                //设置未准备
                redisCache.setCacheMapValue(taskPerson, person.getUserId().toString(),SysConstants.CONSTANT_STR0);
            }
        }
        //更新过期时间
        redisCache.expire(taskPerson,RedisConstants.EXPIRE_TIME_120, TimeUnit.MINUTES);
        return personList;
    }

    /**
     *前端-更新任务参与人员准备状态
     * @param readyStatus
     * @return
     */
    @Override
    @Transactional
    public HashMap<String, Object> updateReady(String readyStatus, String taskNo) {
        if (StringUtils.isBlank(taskNo)) {
            throw new ServiceException("任务编号不能为空！");
        }
        Long userId = SecurityUtils.getUserId();
        String taskPerson = RedisConstants.TASK_PERSON + taskNo;
        redisCache.setCacheMapValue(taskPerson, userId.toString(), readyStatus);

        //统计人数，参训人数和全部准备状态的人数相等就开始任务
        Map<String, String> person = redisCache.hGetAll(taskPerson);
        //如果全部处于准备状态ready为true
        boolean ready = !person.containsValue(SysConstants.CONSTANT_STR0);
        //更新任务和个人任务状态
        if(ready){
            //更新任务
            SysTask  sysTask = new SysTask();
            sysTask.setTaskNo(Long.valueOf(taskNo));
            sysTask.setTaskStatus(TaskStatus. UNDERWAY.getValue());
            sysTask.setStartTime(DateUtils.getNowDate());
            sysTask.setUpdateTime(DateUtils.getNowDate());
            sysTaskMapper.updateSysTaskByTaskNo(sysTask);
            //更新个人任务
            SysUserTask sysUserTask = new SysUserTask();
            sysUserTask.setTaskNo(Long.valueOf(taskNo));
            sysUserTask.setTaskStatus(TaskStatus. UNDERWAY.getValue());
            sysUserTask.setStartTime(DateUtils.getNowDate());
            sysUserTask.setUpdateTime(DateUtils.getNowDate());
            sysUserTaskMapper.updateUserTaskByTaskNo(sysUserTask);
        }

        //组装数据
        HashMap<String, Object> result = new HashMap<>();
        result.put("update", true);
        result.put("ready", ready);
        return result;
    }
}
